
<template>
    <view class="tui-cascade-selection">
        <scroll-view scroll-x scroll-with-animation :scroll-into-view="scrollViewId"
                     :style="{ backgroundColor: headerBgColor }" class="tui-bottom-line"
                     :class="{ 'tui-btm-none': !headerLine }">
            <view class="tui-selection-header" :style="{ height: tabsHeight, backgroundColor: backgroundColor }">
                <view class="tui-header-item" :class="{ 'tui-font-bold': idx === currentTab && bold }"
                      :style="{ color: idx === currentTab ? activeColor : color, fontSize: size + 'rpx' }"
                      :id="`id_${idx}`" @tap.stop="swichNav" :data-current="idx" v-for="(item, idx) in selectedArr"
                      :key="idx">
                    {{ item.text }}
                    <view class="tui-active-line" :style="{ backgroundColor: lineColor }"
                          v-if="idx === currentTab && showLine"></view>
                </view>
            </view>
        </scroll-view>
        <swiper class="tui-selection-list" :current="currentTab" duration="300" @change="switchTab"
                :style="{ height: height, backgroundColor: backgroundColor }">
            <swiper-item v-for="(item, index) in selectedArr" :key="index">
                <scroll-view scroll-y :scroll-into-view="item.scrollViewId" class="tui-selection-item"
                             :style="{ height: height }">
                    <view class="tui-first-item" :style="{ height: firstItemTop }"></view>
                    <view class="tui-selection-cell" :style="{ padding: padding, backgroundColor: backgroundColor }"
                          :id="`id_${subIndex}`" v-for="(subItem, subIndex) in item.list" :key="subIndex"
                          @tap="change(index, subIndex, subItem)">
                        <icon type="success_no_circle" v-if="item.index === subIndex" :color="checkMarkColor"
                              :size="checkMarkSize" class="tui-icon-success"></icon>
                        <image :src="subItem.src" v-if="subItem.src" class="tui-cell-img"
                               :style="{ width: imgWidth, height: imgHeight, borderRadius: radius }"></image>
                        <view class="tui-cell-title"
                              :class="{ 'tui-font-bold': item.index === subIndex && textBold, 'tui-flex-shrink': nowrap }"
                              :style="{ color: item.index === subIndex ? textActiveColor : textColor, fontSize: textSize + 'rpx' }">
                            {{ subItem.text }}
                        </view>
                        <view class="tui-cell-sub_title" :style="{ color: subTextColor, fontSize: subTextSize + 'rpx' }"
                              v-if="subItem.subText">{{ subItem.subText }}</view>
                    </view>
                </scroll-view>
            </swiper-item>
        </swiper>
    </view>
</template>

<script>
export default {
    name: 'tuiCascadeSelection',
    emits: ['change', 'complete'],
    props: {
        /**
         * 如果下一级是请求返回，则为第一级数据，否则所有数据
         * 数据格式
         [{
         src: "",
         text: "",
         subText: "",
         value: 0,
         children:[{
         text: "",
         subText: "",
         value: 0,
         children:[]
         }]
         }]
         * */
        itemList: {
            type: Array,
            default: () => {
                return [];
            }
        },
        /*
           初始化默认选中数据
           [{
            text: "",//选中text
            subText: '',//选中subText
            value: '',//选中value
            src: '', //选中src，没有则传空或不传
            index: 0, //选中数据在当前layer索引
            list: [{src: "", text: "", subText: "", value: 101}] //当前layer下所有数据集合
          }];

           */
        defaultItemList: {
            type: Array,
            value: []
        },
        defaultKey: {
            type: String,
            default: 'text'
        },
        //是否显示header底部细线
        headerLine: {
            type: Boolean,
            default: true
        },
        //header背景颜色
        headerBgColor: {
            type: String,
            default: '#FFFFFF'
        },
        //顶部标签栏高度
        tabsHeight: {
            type: String,
            default: '88rpx'
        },
        //默认显示文字
        text: {
            type: String,
            default: '请选择'
        },
        //tabs 文字大小
        size: {
            type: Number,
            default: 28
        },
        //tabs 文字颜色
        color: {
            type: String,
            default: '#555'
        },
        //选中颜色
        activeColor: {
            type: String,
            default: 'var(--color-primary)'
        },
        //选中后文字加粗
        bold: {
            type: Boolean,
            default: true
        },
        //选中后是否显示底部线条
        showLine: {
            type: Boolean,
            default: true
        },
        //线条颜色
        lineColor: {
            type: String,
            default: 'var(--color-primary)'
        },
        //icon 大小
        checkMarkSize: {
            type: Number,
            default: 15
        },
        //icon 颜色
        checkMarkColor: {
            type: String,
            default: 'var(--color-primary)'
        },
        //item 图片宽度
        imgWidth: {
            type: String,
            default: '40rpx'
        },
        //item 图片高度
        imgHeight: {
            type: String,
            default: '40rpx'
        },
        //图片圆角
        radius: {
            type: String,
            default: '50%'
        },
        //item text颜色
        textColor: {
            type: String,
            default: '#333'
        },
        textActiveColor: {
            type: String,
            default: '#333'
        },
        //选中后字体是否加粗
        textBold: {
            type: Boolean,
            default: true
        },
        //item text字体大小
        textSize: {
            type: Number,
            default: 28
        },
        //text 是否不换行
        nowrap: {
            type: Boolean,
            default: false
        },
        //item subText颜色
        subTextColor: {
            type: String,
            default: '#999'
        },
        //item subText字体大小
        subTextSize: {
            type: Number,
            default: 24
        },
        // item padding
        padding: {
            type: String,
            default: '20rpx 30rpx'
        },
        //占位高度，第一条数据距离顶部距离
        firstItemTop: {
            type: String,
            default: '20rpx'
        },
        //swiper 高度
        height: {
            type: String,
            default: '300px'
        },
        //item  swiper 内容部分背景颜色
        backgroundColor: {
            type: String,
            default: '#FFFFFF'
        },
        //子集数据是否请求返回（默认false，一次性返回所有数据）
        request: {
            type: Boolean,
            default: false
        },
        //子级数据（当有改变时，默认当前选中项新增子级数据，request=true时生效）
        receiveData: {
            type: Array,
            default: () => {
                return [];
            }
        },
        //改变值则重置数据
        reset: {
            type: [Number, String],
            default: 0
        }
    },
    watch: {
        itemList(val) {
            this.initData(val, -1);
        },
        receiveData(val) {
            this.subLevelData(val, this.currentTab);
        },
        reset() {
            this.initData(this.itemList, -1);
        },
        defaultItemList(val) {
            this.setDefaultData(val)
        }
    },
    created() {
        this.setDefaultData(this.defaultItemList)
    },
    data() {
        return {
            currentTab: 0,
            //tab栏scrollview滚动的位置
            scrollViewId: 'id__1',
            selectedArr: []
        };
    },
    methods: {
        setDefaultData(val) {
            let defaultItemList = val || [];
            if (defaultItemList.length > 0) {
                if ((typeof defaultItemList[0] === 'string' || typeof defaultItemList[0] === 'number') && !this
                    .request) {
                    let subi = -1
                    let selectedArr = []
                    for (let j = 0, len = defaultItemList.length; j < len; j++) {
                        let item = defaultItemList[j]
                        let list = []
                        let obj = {}
                        if (j === 0) {
                            list = this.getItemList(-1)
                        } else {
                            list = this.getItemList(j - 1, subi,selectedArr)
                        }
                        subi = this.getDefaultIndex(list, item)
                        if (subi !== -1) {
                            obj = list[subi]
                            selectedArr.push({
                                text: obj.text || this.text,
                                value: obj.value || '',
                                src: obj.src || '',
                                subText: obj.subText || '',
                                index: subi,
                                scrollViewId: `id_${subi}`,
                                list: list
                            })
                        }

                        if (subi === -1) break;
                    }
                    this.selectedArr = selectedArr;
                    this.currentTab = selectedArr.length - 1;
                    this.$nextTick(() => {
                        this.checkCor();
                    });
                } else {
                    defaultItemList.map(item => {
                        item.scrollViewId = `id_${item.index}`;
                    });
                    this.selectedArr = defaultItemList;
                    this.currentTab = defaultItemList.length - 1;
                    this.$nextTick(() => {
                        this.checkCor();
                    });
                }

            } else {
                this.initData(this.itemList, -1);
            }
        },
        getDefaultIndex(arr, val) {
            if (!arr || arr.length === 0 || val === undefined) return -1;
            let index = -1;
            let key = this.defaultKey || 'text'
            for (let i = 0, len = arr.length; i < len; i++) {
                if (arr[i][key] == val) {
                    index = i;
                    break;
                }
            }
            return index;
        },
        initData(data, layer) {
            if (!data || data.length === 0) return;
            if (this.request) {
                //第一级数据
                this.subLevelData(data, layer);
            } else {
                let selectedValue = this.selectedValue || {};
                if (selectedValue.type) {
                    this.setDefaultData(selectedValue);
                } else {
                    this.subLevelData(this.getItemList(layer, -1), layer);
                }
            }
        },
        removeChildren(data) {
            let list = data.map(item => {
                delete item['children'];
                return item;
            });
            return list;
        },
        getItemList(layer, index, selectedArr) {
            let list = [];
            let arr = JSON.parse(JSON.stringify(this.itemList));
            selectedArr = selectedArr || this.selectedArr
            if (layer == -1) {
                list = this.removeChildren(arr);
            } else {
                let value = selectedArr[0].index;
                value = value == -1 ? index : value;
                list = arr[value].children || [];
                if (layer > 0) {
                    for (let i = 1; i < layer + 1; i++) {
                        let val = layer === i ? index : selectedArr[i].index;
                        list = list[val].children || [];
                        if (list.length === 0) break;
                    }
                }
                list = this.removeChildren(list);
            }
            return list;
        },
        //滚动切换
        switchTab: function(e) {
            this.currentTab = e.detail.current;
            this.checkCor();
        },
        //点击标题切换当
        swichNav: function(e) {
            let cur = e.currentTarget.dataset.current;
            if (this.currentTab != cur) {
                this.currentTab = cur;
            }
        },
        checkCor: function() {
            let item = this.selectedArr[this.currentTab];
            item.scrollViewId = 'id__1';
            this.$nextTick(() => {
                setTimeout(() => {
                    let val = item.index < 2 ? 0 : Number(item.index - 2);
                    item.scrollViewId = `id_${val}`;
                }, 2);
            });

            if (this.currentTab > 1) {
                this.scrollViewId = `id_${this.currentTab - 1}`;
            } else {
                this.scrollViewId = `id_0`;
            }
        },
        change(index, subIndex, subItem) {
            let item = this.selectedArr[index];
            if (item.index == subIndex) return;
            item.index = subIndex;
            item.text = subItem.text;
            item.value = subItem.value;
            item.subText = subItem.subText || '';
            item.src = subItem.src || '';
            this.$emit('change', {
                layer: index,
                subIndex: subIndex, //layer=> Array index
                ...subItem
            });

            if (!this.request) {
                let data = this.getItemList(index, subIndex);
                this.subLevelData(data, index);
            }
        },
        //新增子级数据时处理
        subLevelData(data, layer) {
            if (!data || data.length === 0) {
                if (layer == -1) return;
                //完成选择
                let arr = this.selectedArr;
                if (layer < arr.length - 1) {
                    let newArr = arr.slice(0, layer + 1);
                    this.selectedArr = newArr;
                }
                let result = JSON.parse(JSON.stringify(this.selectedArr));
                let lastItem = result[result.length - 1] || {};
                let text = '';
                result.map(item => {
                    text += item.text;
                    delete item['list'];
                    //delete item['index'];
                    delete item['scrollViewId'];
                    return item;
                });
                this.$emit('complete', {
                    result: result,
                    value: lastItem.value,
                    text: text,
                    subText: lastItem.subText,
                    src: lastItem.src
                });
            } else {
                //重置数据（ >layer层级）
                let item = [{
                    text: this.text,
                    subText: '',
                    value: '',
                    src: '',
                    index: -1,
                    scrollViewId: 'id__1',
                    list: data
                }];
                if (layer == -1) {
                    this.selectedArr = item;
                } else {
                    let retainArr = this.selectedArr.slice(0, layer + 1);
                    this.selectedArr = retainArr.concat(item);
                }
                this.$nextTick(() => {
                    this.currentTab = this.selectedArr.length - 1;
                });
            }
        }
    }
};
</script>

<style scoped>
.tui-cascade-selection {
    width: 100%;
    box-sizing: border-box;
}

.tui-selection-header {
    width: 100%;
    display: flex;
    align-items: center;
    position: relative;
    box-sizing: border-box;
}

.tui-bottom-line {
    position: relative;
}

.tui-bottom-line::after {
    width: 100%;
    content: '';
    position: absolute;
    border-bottom: 1rpx solid #eaeef1;
    -webkit-transform: scaleY(0.5) translateZ(0);
    transform: scaleY(0.5) translateZ(0);
    transform-origin: 0 100%;
    bottom: 0;
    right: 0;
    left: 0;
}

.tui-btm-none::after {
    border-bottom: 0 !important;
}

.tui-header-item {
    max-width: 240rpx;
    padding: 15rpx 30rpx;
    box-sizing: border-box;
    flex-shrink: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    position: relative;
}

.tui-font-bold {
    font-weight: bold;
}

.tui-active-line {
    width: 60rpx;
    height: 6rpx;
    border-radius: 4rpx;
    position: absolute;
    bottom: 0;
    right: 0;
    left: 50%;
    transform: translateX(-50%);
}

.tui-selection-cell {
    width: 100%;
    box-sizing: border-box;
    display: flex;
    align-items: center;
}

.tui-icon-success {
    margin-right: 12rpx;
}

.tui-cell-img {
    margin-right: 12rpx;
    flex-shrink: 0;
}

.tui-cell-title {
    word-break: break-all;
}

.tui-flex-shrink {
    flex-shrink: 0;
}

.tui-font-bold {
    font-weight: bold;
}

.tui-cell-sub_title {
    margin-left: 20rpx;
    word-break: break-all;
}

.tui-first-item {
    width: 100%;
}
</style>
